package com.zxy.ziems.collector.utils;


/**
 * @author 10348359
 * @create 2024-04-12 14:39 */
public class IntegerUtil {

    private IntegerUtil() {
        // NOOP
    }

    /**
     * 将short转换为字节数组
     *
     * @param data         short数据
     * @param littleEndian true:小端，false：大端
     * @return 字节数组
     */
    public static byte[] toByteArray(int data, boolean littleEndian) {
        byte[] bytes = new byte[4];

        if (littleEndian) {
            bytes[0] = (byte) ((data) & 0xFF);
            bytes[1] = (byte) ((data >> 8) & 0xFF);
            bytes[2] = (byte) ((data >> 16) & 0xFF);
            bytes[3] = (byte) ((data >> 24) & 0xFF);
        } else {
            bytes[0] = (byte) ((data >> 24) & 0xFF);
            bytes[1] = (byte) ((data >> 16) & 0xFF);
            bytes[2] = (byte) ((data >> 8) & 0xFF);
            bytes[3] = (byte) ((data) & 0xFF);
        }
        return bytes;
    }

    /**
     * 将int转换为字节数组，默认采用大端模式
     *
     * @param data int数据
     * @return 字节数组
     */
    public static byte[] toByteArray(int data) {
        return toByteArray(data, false);
    }

    /**
     * 将long转换为字节数组，默认采用大端模式
     *
     * @param data long数据
     * @return 字节数组
     */
    public static byte[] toByteArray(long data) {
        return toByteArray((int) data, false);
    }

    /**
     * 将long转换为字节数组，并自定义获取字节数，默认采用大端模式
     *
     * @param data   long数据
     * @param offset 偏移量
     * @param length 读取长度
     * @return 字节数组
     */
    public static byte[] toCustomByteArray(long data, int offset, int length) {
        if (offset + length > 4) {
            throw new IndexOutOfBoundsException("offset + length > 4");
        }
        byte[] bytes = toByteArray((int) data, false);
        byte[] res = new byte[length];
        System.arraycopy(bytes, offset, res, 0, length);
        return res;
    }

    /**
     * 将字节数组转换为int32
     *
     * @param data 字节数组
     * @return int32数据
     */
    public static int toInt32(byte[] data) {
        return toInt32(data, 0, false);
    }

    /**
     * 将字节数组转换为int32
     *
     * @param data   字节数组
     * @param offset 偏移量
     * @return int32数据
     */
    public static int toInt32(byte[] data, int offset) {
        return toInt32(data, offset, false);
    }

    /**
     * 将字节数组转换为int32
     *
     * @param data         字节数组
     * @param offset       偏移量
     * @param littleEndian true：小端模式，false：大端模式
     * @return int32数据
     */
    public static int toInt32(byte[] data, int offset, boolean littleEndian) {
        if (data.length < 4) {
            throw new IndexOutOfBoundsException("data小于4个字节");
        }
        if (offset + 4 > data.length) {
            throw new IndexOutOfBoundsException("offset + 4 > 字节长度");
        }
        int b = littleEndian ? 3 : 0;
        int d = littleEndian ? 1 : -1;
        return (((data[offset + b - d * 0] & 0xFF) << 24)
                | ((data[offset + b - d * 1] & 0xFF) << 16)
                | ((data[offset + b - d * 2] & 0xFF) << 8)
                | ((data[offset + b - d * 3] & 0xFF) << 0));
    }

    /**
     * 将字节数组转换为int32
     *
     * @param data   字节数组
     * @param offset 偏移量
     * @return int32数据
     */
    public static int toInt32In3Bytes(byte[] data, int offset) {
        return toInt32In3Bytes(data, offset, false);
    }

    /**
     * 将字节数组转换为int32
     *
     * @param data         字节数组
     * @param offset       偏移量
     * @param littleEndian true：小端模式，false：大端模式
     * @return int32数据
     */
    public static int toInt32In3Bytes(byte[] data, int offset, boolean littleEndian) {
        if (data.length < 3) {
            throw new IndexOutOfBoundsException("data小于3个字节");
        }
        if (offset + 3 > data.length) {
            throw new IndexOutOfBoundsException("offset + 3 > 字节长度");
        }
        int b = littleEndian ? 2 : 0;
        int d = littleEndian ? 1 : -1;
        return (((data[offset + b - d * 0] & 0xFF) << 16)
                | ((data[offset + b - d * 1] & 0xFF) << 8)
                | ((data[offset + b - d * 2] & 0xFF) << 0));
    }

    /**
     * 将字节数组转换为uint32
     *
     * @param data 字节数组
     * @return uint32数据
     */
    public static long toUInt32(byte[] data) {
        return toUInt32(data, 0, false);
    }

    /**
     * 将字节数组转换为uint32
     *
     * @param data   字节数组
     * @param offset 偏移量
     * @return uint32数据
     */
    public static long toUInt32(byte[] data, int offset) {
        return toUInt32(data, offset, false);
    }

    /**
     * 将字节数组转换为uint32
     *
     * @param data         字节数组
     * @param offset       偏移量
     * @param littleEndian true：小端模式，false：大端模式
     * @return uint32数据
     */
    public static long toUInt32(byte[] data, int offset, boolean littleEndian) {
        if (data.length < 4) {
            throw new IndexOutOfBoundsException("data小于4个字节");
        }
        if (offset + 4 > data.length) {
            throw new IndexOutOfBoundsException("offset + 4 > 字节长度");
        }
        int b = littleEndian ? 3 : 0;
        int d = littleEndian ? 1 : -1;
        return (((data[offset + b - d * 0] & 0xFF) << 24)
                | ((data[offset + b - d * 1] & 0xFF) << 16)
                | ((data[offset + b - d * 2] & 0xFF) << 8)
                | ((data[offset + b - d * 3] & 0xFF) << 0)) & 0xFFFFFFFFL;
    }

    /**
     * 将字节数组转换为int64
     *
     * @param data         字节数组
     * @param offset       偏移量
     * @param littleEndian true：小端模式，false：大端模式
     * @return int64数据
     */
    public static long toInt64(byte[] data, int offset, boolean littleEndian) {
        if (data.length < 8) {
            throw new IndexOutOfBoundsException("data小于8个字节");
        }
        if (offset + 8 > data.length) {
            throw new IndexOutOfBoundsException("offset + 8 > 字节长度");
        }

        int b = littleEndian ? 7 : 0;
        int d = littleEndian ? 1 : -1;
        long l = ((long) (data[offset + b - d * 0] & 0xFF) << 56)
                | ((long) (data[offset + b - d * 1] & 0xFF) << 48)
                | ((long) (data[offset + b - d * 2] & 0xFF) << 40)
                | ((long) (data[offset + b - d * 3] & 0xFF) << 32)
                | ((long) (data[offset + b - d * 4] & 0xFF) << 24)
                | ((long) (data[offset + b - d * 5] & 0xFF) << 16)
                | ((long) (data[offset + b - d * 6] & 0xFF) << 8)
                | (long) (data[offset + b - d * 7] & 0xFF);
        return  l;
    }

    /**
     * 将字节数组转换为int64
     * 将各个寄存器地址的十六进制数依次转换为十进制数，
     * 4个十进制数依次乘以10^12、10^8、 10^4、10^0，
     * 即 0000×10^12+0000×10^8+8264×10^4+3912×10^0=82643912Wh（PM 表实际显示值）
     *
     * @param data         字节数组
     * @param offset       偏移量
     * @param littleEndian true：小端模式，false：大端模式
     * @return int64数据
     */
    public static long toInt64_1(byte[] data, int offset, boolean littleEndian) {
        if (data.length < 8) {
            throw new IndexOutOfBoundsException("data小于8个字节");
        }
        if (offset + 8 > data.length) {
            throw new IndexOutOfBoundsException("offset + 8 > 字节长度");
        }

        int b = littleEndian ? 0 : 6;
        int d = littleEndian ? -1 : 1;
        return  (long) ShortUtil.toUInt16(data, offset + b - d * 0, littleEndian) * (long)Math.pow(10, 12)
                + (long) ShortUtil.toUInt16(data, offset + b - d * 2, littleEndian) * (long)Math.pow(10, 8)
                + (long) ShortUtil.toUInt16(data, offset + b - d * 4, littleEndian) * (long)Math.pow(10, 4)
                + (long) ShortUtil.toUInt16(data, offset + b - d * 6, littleEndian) * (long)Math.pow(10, 0);
    }
}
